package cn.net.ecode.modules.msg.task;

import java.util.Date;
import java.util.List;
import java.util.Map;

import cn.net.ecode.common.config.Global;
import cn.net.ecode.common.mapper.JsonMapper;
import cn.net.ecode.common.persistence.Page;
import cn.net.ecode.common.service.BaseService;
import cn.net.ecode.common.utils.HttpClientUtils;
import cn.net.ecode.common.utils.StringUtils;
import cn.net.ecode.modules.msg.entity.MessageRecord;
import cn.net.ecode.modules.msg.service.MessageService;

import com.google.common.collect.Lists;
import com.google.common.collect.Maps;

/**
 * 消息中心发送服务（调度任务）
 * @author ThinkGem
 * @version 2015-11-16
 */
public class MsgCenterSendTask extends BaseService {

	/**
	 * 消息记录服务
	 */
	private MessageService messageService;
	
	/**
	 * 消息服务器参数
	 */
	private String servUrl = Global.getProperty("msg.center.serviceUrl");
	private String username = Global.getProperty("msg.center.loginUsername");
	private String password = Global.getProperty("msg.center.loginPassword");

	/**
	 * 存储的会话编号，则通过getSid()获取。
	 */
	private static String __sid;
	
	/**
	 * 执行消息发送任务
	 */
	public void execute(){
		logger.info("==== 消息发送服务（启动） ====================");
		
		if(StringUtils.isBlank(servUrl) && StringUtils.isBlank(username)
				&& StringUtils.isBlank(password)){

			logger.error("请在app.properties中配置msg.center.serviceUrl、msg.center."
					+ "loginUsername、msg.center.loginPassword参数。");
			
		}else{
			
			MessageRecord mr = null;
			String sid = getSid();
			
			// 直到发送完成
			while(sid != null){
				
				// 查询未发送的消息
				List<MessageRecord> list = findMessageList();
				
				// 如果没有已经发送的消息，则跳出循环
				if (list.size() == 0){
					break;
				}
				
				// 发送失败个数
				int failCount = 0;
				
				// 根据消息保存顺序发送消息
				for (int i=list.size()-1; i>=0; i--){
					mr = list.get(i);
		
					String reqUrl = "/msg/message/saveRecordByJson?__sid=" + sid;
					String jsonString = JsonMapper.toJsonString(mr);
					List<Map<String, Object>> result = postJson(reqUrl, jsonString);
					
					if (checkResult(result)){
						// 发送成功则，更新消息状态为已读
						updateMessageStatus(mr.getId(), MessageRecord.STATUS_READ);
					}else{
						failCount++;
					}
					
				}
				
				// 如果没有一条消息能够发送成功，则停止下一步发送
				if (list.size() == failCount){
					logger.warn("没有一条消息能够发送成功，请检查你的消息服务配置。");
					break;
				}
				// 提示失败的消息个数
				else if (failCount > 0){
					logger.warn("你有“" + failCount + "”条消息没有发送成功！");
				}
			}
			
		}
		
//		try {
//			Thread.sleep(5000);
//		} catch (InterruptedException e) {
//			e.printStackTrace();
//		}
		logger.info("==== 消息发送服务（结束） ====================");
	}

	/**
	 * 获取待发送的消息列表（发送时间倒序）默认获取30条
	 * @return
	 */
	public List<MessageRecord> findMessageList(){
		Page<MessageRecord> page = new Page<>(1, 30, -1);
		MessageRecord mr = new MessageRecord();
		mr.setStatus(MessageRecord.STATUS_UNDELIVERED);
		mr.getMessage().setType("sendTask"); // 发送服务查询条件（不查询内部消息）
		mr.getMessage().setEndSendDate(new Date());
		page = messageService.findMessageRecordPage(page, mr);
		return page.getList();
	}
	
	/**
	 * 更新发送状态，为已读
	 * @return
	 */
	public void updateMessageStatus(String mrId, String status){
		MessageRecord mr = new MessageRecord(mrId);
		mr.setReceiveDate(new Date());
		mr.setReadDate(new Date());
		mr.setStatus(status);
		messageService.updateMsgRecord(mr);
	}
	
	/**
	 * 获取有效的会话编号
	 */
	public String getSid(){
		// 验证原有的sid是否失效，如果失效，则将sid设置为null，以方便获取新的sid。
		if (__sid != null){
			String url = "?__sid=" + __sid;
			List<Map<String, Object>> result = post(url, null);
			if (!checkResult(result)){
				__sid = null; // 验证失败，则设置 __sid为空。
			}
		}
		// 如果没有有效的sid，则重新登录并获取新的sid
		if (__sid == null){
			String url = "/login?username=" + username + "&password=" + password;
			List<Map<String, Object>> result = post(url, null);
			if (checkResult(result)){
				__sid = (String)result.get(0).get("sessionid");
			}else{
				logger.warn("获取权限失败，请检查你的消息服务配置。错误信息：" + (String)getOneResult(result).get("message"));
			}
		}
		return __sid;
	}
	
	/**
	 * 发送post请求
	 */
	public List<Map<String, Object>> post(String url, Map<String, String> data){
		List<Map<String, Object>> result = Lists.newArrayList();
		String body = HttpClientUtils.ajaxPost(servUrl + url, data);
		logger.info("post: " + url + " , body: " + body);
		result = JsonMapper.fromJsonStringForMapList(body);
		return result;
	}
	
	/**
	 * 发送post请求，join参数
	 */
	public List<Map<String, Object>> postJson(String url, String jsonString){
		List<Map<String, Object>> result = Lists.newArrayList();
		String body = HttpClientUtils.ajaxPostJson(servUrl + url, jsonString);
		logger.info("post: " + url + " , body: " + body);
		result = JsonMapper.fromJsonStringForMapList(body);
		return result;
	}
	
	/**
	 * 获取第一行结果
	 */
	public static Map<String, Object> getOneResult(List<Map<String, Object>> result){
		if (result.size() > 0){
			return result.get(0);
		}else{
			return Maps.newHashMap();
		}
	}
	
	/**
	 * 验证结果是否请求成功
	 */
	public static boolean checkResult(List<Map<String, Object>> result){
		return StringUtils.toBoolean(getOneResult(result).get("result"));
	}
	
	////////////////// 以下set方法，通过spring的xml配置注入 ///////////////
	
	public void setMessageService(MessageService messageService) {
		this.messageService = messageService;
	}

}
